<?php

namespace Common\Model;

class ModelModel extends BaseModel
{
    protected $_auto = array(
        array('create_time', NOW_TIME,),
        array('update_time', NOW_TIME, 3),
    );
    protected $_validate = array(
        array('name', 'require', '请填写模型标识',),
        array('name', '', '模型标识已存在', 0, 'unique',),
        array('title', 'require', '请填写模型名称',),
        array('title', '', '模型已存在', 0, 'unique',),
    );
    protected $delete_list = array();
    protected $update_list = array();

    public function parseListGrid($data) {
        $array = preg_split('/[\r\n]+/', trim($data, "\r\n"));
        $n = array();
        foreach ($array as $row) {
            $val = htmlspecialchars_decode(substr($row, strpos($row, ':')+1));
            $key = substr($row,0, strpos($row, ':'));
            $json = json_decode($val,true);
            if($json) {
                $n[] = array_merge($json, array(
                    'field'=>$key,
                ));
            }else {
                $n[] = array(
                    'field'=>$key,
                    'title'=>$val,
                );
            }
        }
        return $n;
    }

    // 建立模型
    public function _after_insert($data, $options)
    {
        parent::_after_insert($data, $options);
        if ($data['name']) {
            $tbn = C('DB_PREFIX') . $data['name'];
            $hasPk = 'id';
            $engine = 'MyISAM';
            if (isset($data['primary_key'])) {
                $hasPk = $data['primary_key'];
            }
            if ($data['engine_type']) {
                $engine = $data['engine_type'];
            }
            $comment = $data['title'];
            $this->dropTable($tbn); // 删除
            $this->createTable($tbn, $hasPk, $engine, $comment); // 创建
            // 自带字段
            $fieldData = array();
            $fieldData[] = array(
                'name' => 'create_time',
                'title' => '创建时间',
                'form' => 'num',
                'attribute' => 'int NOT NULL',
                'create_time' => NOW_TIME,
                'update_time' => NOW_TIME,
                'model_id' => $data['id'],
                'auto_rule' => 'time',
                'auto_time' => '1',
                'auto_type' => 'function',
                'is_show' => 0,
                'is_must' => 0,
            );
            $fieldData[] = array(
                'name' => 'update_time',
                'title' => '更新时间',
                'form' => 'num',
                'attribute' => 'int NOT NULL',
                'create_time' => NOW_TIME,
                'update_time' => NOW_TIME,
                'model_id' => $data['id'],
                'auto_rule' => 'time',
                'auto_time' => '3',
                'auto_type' => 'function',
                'is_show' => 0,
                'is_must' => 0,
            );
            M('ModelField')->addAll($fieldData);
        }
    }


    // 编辑模型
    // 前置
    public function _before_update(&$data, $options)
    {
        parent::_before_update($data, $options);
        if ($options['where']) {
            $this->update_list = $this->where($options['where'])->field('name,title,primary_key,engine_type')->select();
        }
    }

    // 后置
    public function _after_update($data, $options)
    {
        parent::_after_update($data, $options);
        if ($this->update_list) {
            foreach ($this->update_list as &$row) {
                $tbn = $old_tbn = C('DB_PREFIX') . $row['name'];
                // 修改表名
                if ($data['name']) {
                    $tbn = $new_tbn = C('DB_PREFIX') . $data['name'];
                    $this->updateTableName($old_tbn, $new_tbn);
                }
                // 修改表注释
                if ($data['title']) {
                    $this->updateTableComment($tbn, $data['title']);
                }
                // 修改数据表引擎
                if ($data['engine_type']) {
                    $this->updateTableEngine($tbn, $data['engine_type']);
                }
                // 修改主键
                if (isset($data['primary_key'])) {
                    if (empty($data['primary_key'])) {
                        // 如果为空则删除主键
                        $this->dropPK($tbn);
                    } else {
                        // 否则只修改列名
                        $this->alterColumnAttr($tbn, $row['primary_key'], $data['primary_key'], 'int AUTO_INCREMENT');
                    }
                }
            }
        }
    }

    // 删除模型
    public function _before_delete($options)
    {
        parent::_before_delete($options);
        if ($options['where']) {
            $this->delete_list = $this->where($options['where'])->field('id,name')->select(); // 先记录被删除的数据
        }
    }

    public function _after_delete($data, $options)
    {
        parent::_after_delete($data, $options);
        if ($this->delete_list) {
            // 如果删除成功则开始删除数据表
            foreach ($this->delete_list as $item) {
                $tbn = C('DB_PREFIX') . $item['name'];
                $this->dropTable($tbn);
                M('ModelField')->where(array('model_id' => $item['id']))->delete();
            }
            $this->delete_list = array(); // 释放
        }
    }

    /**
     * 为模型创建数据表
     * 自动生成created_at、updated_at字段
     * @param  string $tableName 数据表名称
     * @param  boolean $hasPk 是否含有主键
     * @param  string $engine 引擎类型
     * @return boolean            是否创建成功
     */
    public function createTable($tableName, $hasPk = 'id', $engine = 'InnoDB', $comment = '')
    {
        if (!$tableName) return false;

        $pkSql = '';
        if ($hasPk) {
            // id主键的sql
            $pkSql = "`{$hasPk}` int PRIMARY KEY NOT NULL "
                . "AUTO_INCREMENT COMMENT '表主键',";
        }

        $sql = "CREATE TABLE `{$tableName}` ("
            . $pkSql
            . "`create_time` int NOT NULL COMMENT '创建时间',"
            . "`update_time` int NOT NULL COMMENT '更新时间'"
            . ") ENGINE={$engine} CHARSET=utf8 COMMENT='{$comment}'";
        // 创建数据表
        if (false === M()->execute($sql)) {
            return false;
        }
        return true;
    }

    /**
     * 删除数据表
     * @param  string $tableName 表名
     * @return boolean
     */
    public function dropTable($tableName)
    {
        $sql = "DROP TABLE IF EXISTS `{$tableName}`";
        if (false === $this->execute($sql)) {
            return false;
        }

        return true;
    }

    /**
     * 得到建表信息
     * @param  string $tableName
     * @return string
     */
    public function getCreateTableSql($tableName)
    {
        if (!isset($tableName) || empty($tableName)) {
            return '';
        }

        // 设置字段名加上`
        $this->execute('SET SQL_QUOTE_SHOW_CREATE = 1');
        $createTableSql = $this->execute("SHOW CREATE TABLE `{$tableName}`");
        return $createTableSql[0]['Create Table'] . ";";
    }

    /**
     * 修改表名
     * @param  string $tableName 需要修改的表名
     * @param  string $newTableName 新表名
     * @return boolean
     */
    public function updateTableName($tableName, $newTableName)
    {
        $sql = "ALTER TABLE `{$tableName}` RENAME TO `{$newTableName}`";
        return $this->execute($sql);
    }

    /**
     * 修改表注释
     * @param $tableName
     * @param $comment
     * @return false|int
     */
    public function updateTableComment($tableName, $comment)
    {
        $sql = 'alter table ' . $tableName . ' comment \'' . $comment . '\'';
        return $this->execute($sql);
    }

    /**
     * 修改表引擎
     * @param $tableName
     * @param $engine
     * @return false|int
     */
    public function updateTableEngine($tableName, $engine)
    {
        $sql = 'ALTER TABLE ' . $tableName . ' ENGINE=' . $engine;
        return $this->execute($sql);
    }

    /**
     * 删除数据表主键
     * @param $tableName
     * @return false|int
     */
    public function dropPK($tableName)
    {
        $sql = 'alter table ' . $tableName . ' drop primary key';
        return $this->execute($sql);
    }

    /**
     * 得到重建数据表的sql
     * @param  string $tableName
     * @return string
     */
    public function getRebuildTableSql($tableName)
    {
        $sql = $this->getDropTableSql($tableName) . "\r\n";
        $sql .= $this->getCreateTableSql($tableName) . "\r\n";

        return $sql;
    }

    /**
     * 添加字段到数据表
     * @param string $tn 数据表名称
     * @param string $cn 字段名称
     * @param string $type 字段类型
     * @param int $length 字段长度
     * @param mixed $value 字段默认值
     * @param string $comment 字段注释
     * @return mixed
     */
    public function addColumn($tn, $cn, $type, $length, $value, $comment)
    {
        // 添加字段的sql
        $sql = "ALTER TABLE `{$tn}` ADD COLUMN `{$cn}` {$type}";

        // 类型长度
        if (isset($length) && 0 != $length) {
            $sql .= "({$length}) ";
        }

        // 默认值
        if (isset($value) && '' != $value) {
            $text = array('CHAR', 'VARCHAR', 'TEXT',
                'TINYTEXT', 'MEDIUMTEXT', 'LONGTEXT');

            if (in_array($type, $text)) {
                // 字符默认值
                $sql .= " NOT NULL DEFAULT '{$value}' ";
            } else {
                // 数值型
                $sql .= " NOT NULL DEFAULT {$value} ";
            }
        }

        // 字段注释
        if (isset($comment) && '' != $comment) {
            $sql .= " COMMENT '{$comment}' ";
        }

        return $this->execute($sql);
    }

    /**
     * 修改列基本属性
     * @param  string $tn 数据表名
     * @param  string $cn 需要修改的列名
     * @param  string $ncn 新列名
     * @param  string $type 列的类型
     * @param  int $len 字段长度
     * @param  string $cm 字段注释
     * @return mixed
     */
    public function alterColumnAttr($tn, $cn, $ncn, $type, $len, $cm)
    {
        $sql = "ALTER TABLE {$tn} CHANGE COLUMN {$cn} {$ncn} {$type} ";

        if (isset($len) && 0 !== $len) {
            $sql .= "({$len}) ";
        }

        if (isset($cm)) {
            $sql .= "COMMENT '{$cm}'";
        }

        return $this->execute($sql);
    }

    /**
     * 删除列默认值
     * @param  string $tn 数据表名
     * @param  string $cn 需要修改的列名
     * @return mixed
     */
    public function dropColumnDefault($tn, $cn)
    {
        $sql = "ALTER TABLE {$tn} ALTER COLUMN {$cn} DROP DEFAULT";

        return $this->execute($sql);
    }

    /**
     * 设置列默认值
     * @param  string $tn 数据表名
     * @param  string $cn 需要修改的列名
     * @param  string $value 字段默认值
     * @return mixed
     */
    public function setColumnDefault($tn, $cn, $value)
    {
        $sql = "ALTER TABLE {$tn} ALTER COLUMN {$cn} set DEFAULT '{$value}'";

        return $this->execute($sql);
    }

    /**
     * 修改列默认值
     * @param  string $tn 数据表名
     * @param  string $cn 需要修改的列名
     * @param  string $value 字段默认值
     * @return mixed
     */
    public function alterColumnValue($tn, $cn, $value)
    {
        $this->dropColumnDefault($tn, $cn);

        return $this->setColumnDefault($tn, $cn, $value);
    }

    /**
     * 从数据表中删除字段
     * @param string $tn 数据表名称
     * @param string $cn 字段名称
     * @return mixed
     */
    public function dropColumn($tn, $cn)
    {
        $sql = "ALTER TABLE `{$tn}` DROP `{$cn}`";

        return $this->execute($sql);
    }
}